/**
 * Program   :   TableDefine.java
 * Author    :   shadow guo
 * Create    :   2013-6-23 上午11:44:43
 *
 * Copyright 2008 by Tongfu Information Technology Co. Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Tongfu Information Technology Co. Ltd. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Tongfu Information Technology Co. Ltd.
 * 
 */
package com.tongfusoft.web.utils;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang3.StringUtils;
import org.yaml.snakeyaml.Yaml;

import com.tongfusoft.web.core.annotation.FieldName;
import com.tongfusoft.web.core.data.BaseData;

public class TableDefine {
	public static final String lastUpdDate = "lastUpdDate";
	public static final String createdDate = "createdDate";
	public static final String createdBy = "createdBy";
	public static final String status = "status";
	public static final String TAB = "    ";
	public static final String BR = "\n";
	
	
	private String tableName;
	private String tableRemark;
	private List<String> pkColumnNames = new ArrayList<String>(2);
	private String tableSchema;
	private Map<String,List<String>> uniqeIndex = new HashMap<String,List<String>>();

	private List<ColumnDefine> columns = new ArrayList<ColumnDefine>(10);
	
	public void addUniqeIndexColumn(String indexName,String column){
		if(uniqeIndex.containsKey(indexName)){
			uniqeIndex.get(indexName).add(column);
		}else{
			List<String> index = new ArrayList<String>();
			index.add(column);
			uniqeIndex.put(indexName, index);
		}
	}

	public Map<String, List<String>> getUniqeIndex() {
		return uniqeIndex;
	}

	public void setUniqeIndex(Map<String, List<String>> uniqeIndex) {
		this.uniqeIndex = uniqeIndex;
	}

	public String getTableSchema() {
		return tableSchema;
	}

	public void setTableSchema(String tableSchema) {
		this.tableSchema = tableSchema;
	}

	public void addPkColumn(String column){
		this.getPkColumnNames().add(column);
	}
	
	public void addColumn(ColumnDefine column){
		this.getColumns().add(column);
	}
	
	public List<String> getPkColumnNames() {
		return pkColumnNames;
	}

	public void setPkColumnNames(List<String> pkColumnNames) {
		this.pkColumnNames = pkColumnNames;
	}

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public String getTableRemark() {
		return tableRemark;
	}

	public void setTableRemark(String tableRemark) {
		this.tableRemark = tableRemark;
	}

	public List<ColumnDefine> getColumns() {
		return columns;
	}

	public void setColumns(List<ColumnDefine> columns) {
		this.columns = columns;
	}

	public String warpTableName() {
		String[] warpNames = StringUtils.split(tableName.toLowerCase(), "_");
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < warpNames.length; i++) {
			sb.append(warpNames[i].substring(0, 1).toUpperCase());
			if (warpNames[i].length() > 1) {
				sb.append(warpNames[i].substring(1));
			}
		}
		return sb.toString();
	}
	
	private void processSb(StringBuffer sb){
		int count = sb.length();
		for(int i=count-1;i>=0 ;i--){
			if(sb.charAt(i) != ' ' || sb.charAt(i) != '\r' || sb.charAt(i) != '\n'){
				if(sb.charAt(i) == ','){
					sb.deleteCharAt(i);
					return;
				}
			}
		}
	}
	
	public String getCUDSQL(){
		StringBuffer sb = new StringBuffer();
		sb.append(this.getInsertSQL()).append(BR);
		sb.append(this.getUpdateSQL()).append(BR);
		sb.append(this.getDeleteSqlByUpdate()).append(BR);
		
		return sb.toString();
	}
	
	public String getInsertSQL() {
		int index = 0;
		StringBuffer sb = new StringBuffer();
		sb.append("---").append(BR);
		sb.append("#新增").append(this.getTableRemark()).append(BR);
		sb.append("insert#").append(this.getTableName()).append(" : |").append(BR);
		sb.append(TAB);
		sb.append("insert into ").append(this.getTableName()).append(" (");
		for (int i = 0; i < this.getColumns().size(); i++) {
			ColumnDefine column = this.getColumns().get(i);

			if (!StringUtils.equalsIgnoreCase(column.getWarpName(), status)) { 
				sb.append(column.getFieldName()).append(",");

				if (++index % 2 == 0) {
					sb.append(BR).append(TAB);
				}
			}

		}

		processSb(sb);

		sb.append(" ) ").append(BR).append("       values ( ");

		index = 0;
		for (int i = 0; i < this.getColumns().size(); i++) {
			ColumnDefine column = this.getColumns().get(i);
			if (!StringUtils.equalsIgnoreCase(column.getWarpName(), status)) { // status不insert
				sb.append("#{").append(column.getWarpName()).append(",")
						.append(column.getJavaType()).append(",")
						.append(column.getJdbcType()).append("}").append(",");
				
				if (++index % 5 == 0 ) {
					sb.append(BR).append(TAB);
				}
			}
		}

		processSb(sb);

		sb.append(" ) ").append(BR);

		return sb.toString();
	}

	public String getUpdateSQL() {
		int index = 0;
		StringBuffer sb = new StringBuffer();
		sb.append("---").append(BR);
		sb.append("#更新").append(this.getTableRemark()).append(BR);
		sb.append("update#").append(this.getTableName()).append(" : |").append(BR);
		sb.append("    ");
		sb.append("update ").append(this.getTableName()).append(" set ");

		String where = "";

		for (int i = 0; i < this.getColumns().size(); i++) {
			ColumnDefine column = this.getColumns().get(i);

			if (!this.getPkColumnNames().contains(column.getFieldName())) {
				if(!StringUtils.equalsIgnoreCase(column.getWarpName(),
							status)
					&& !StringUtils.equalsIgnoreCase(column.getWarpName(),
							createdDate)
					&& !StringUtils.equalsIgnoreCase(column.getWarpName(),
							createdBy)){
						sb.append(column.getFieldName()).append("=").append("#{")
							.append(column.getWarpName()).append(",")
							.append(column.getJavaType()).append(",")
							.append(column.getJdbcType()).append("}")
							.append(",");

					if (++index % 2 == 0) {
						sb.append(BR).append(TAB);
					}
				}
			}

		}
		
		processSb(sb);
		
		sb.append(BR);
		
		sb.append(TAB).append("where ");
		
		for(int i=0;i<this.getPkColumnNames().size();i++){
			ColumnDefine column = findColumn(this.getPkColumnNames().get(i));
			
			if(column != null){
				sb.append(this.getPkColumnNames().get(i)).append(" = #{").append(column.getWarpName()).append("} ");
				
				if(i < this.getPkColumnNames().size() -1){
					sb.append( " and ");
				}
			}
		}

		sb.append(BR);
		
		return sb.toString();
	}

	private ColumnDefine findColumn(String columnName){
		for(ColumnDefine column : this.getColumns()){
			if(StringUtils.equals(column.getFieldName(), columnName)){
				return column;
			}
		}
		
		return null;
	}

	public String getDeleteSqlByUpdate(){
		StringBuffer sb = new StringBuffer();
		sb.append("---").append(BR);
		sb.append("#删除").append(this.getTableRemark()).append(BR);
		
		sb.append("delete#").append(tableName).append(" : |").append(BR);
		sb.append("    ");
		sb.append("update ").append(tableName).append(" set status = '0' where  ");
		
		for(int i=0;i<this.getPkColumnNames().size();i++){
			ColumnDefine column = findColumn(this.getPkColumnNames().get(i));
			
			if(column != null){
				sb.append(this.getPkColumnNames().get(i)).append(" = #{").append(column.getWarpName()).append("} ");
				
				if(i < this.getPkColumnNames().size() -1){
					sb.append( " and ");
				}
			}
		}

		sb.append(BR);

		return sb.toString();
	}

	public String getBean() throws FileNotFoundException {
		StringBuffer sb = new StringBuffer();
		StringBuffer warpPkName = new StringBuffer();

		for (int i = 0; i < this.getColumns().size(); i++) {
			ColumnDefine column = this.getColumns().get(i);

			if (!StringUtils.equals(column.getWarpName(),
					BaseData.FIELD_CREATEDBY)
					&& !StringUtils.equals(column.getWarpName(),
							BaseData.FIELD_CREATEDDATE)
					&& !StringUtils.equals(column.getWarpName(),
							BaseData.FIELD_LASTUPDBY)
					&& !StringUtils.equals(column.getWarpName(),
							BaseData.FIELD_LASTUPDDATE)) {
				// NUMBER,DATE,VARCHAR2
				//添加注释
				sb.append("/**").append(BR).append(column.getRemark()).append(BR).append("*/").append(BR);
				sb.append("@FieldName(value=\"").append(column.getFieldName()).append("\")").append(BR);
				if (StringUtils.equals(column.getFieldType(), "DATE")) {
					sb.append("private Date ").append(column.getWarpName())
							.append(";").append(BR);
				} else if (StringUtils.equals(column.getFieldType(), "NUMBER")) {
					if (column.getScale() == 0) {
						sb.append("private int ").append(column.getWarpName())
								.append(";").append(BR);
					} else {
						sb.append("private double ")
								.append(column.getWarpName()).append(";")
								.append(BR);
					}
				} else {
					sb.append("private String ").append(column.getWarpName())
							.append(";").append(BR);
				}

			}
		}
		
		warpPkName.append("\"");
		for(int i=0;i<this.getPkColumnNames().size();i++){
			ColumnDefine column = findColumn(this.getPkColumnNames().get(i));
			warpPkName.append(column.getWarpName());
			if(i < this.getPkColumnNames().size() - 1){
				warpPkName.append(",");
			}
		}
		warpPkName.append("\"");

		Yaml yaml = new Yaml();

		String content = "";
		for (Object config : yaml.loadAll(this.getClass().getResourceAsStream(
				"/bean.yaml"))) {
			Map<String, Object> properties = (Map<String, Object>) config;
			if (properties.containsKey("bean")) {
				content = (String) properties.get("bean");
				break;
			}
		}

		content = String.format(content,getUniqeCheck(), warpTableName(), sb.toString(),
				warpPkName.toString(), "\"" + tableName + "\"") + BR;

		return content;
	}
	
	private String getUniqeCheck(){
		if(uniqeIndex.size() > 0){
			StringBuffer sb = new StringBuffer();
			sb.append("@UniqueCheck(value=\"");
			
			//组装成json格式
			JSONArray jsonArray = new JSONArray();
			Iterator<Entry<String,List<String>>> iter = uniqeIndex.entrySet().iterator();
			while(iter.hasNext()){
				JSONObject json = new JSONObject();
				Entry<String,List<String>> entry = iter.next();
				for(int i=0;i<entry.getValue().size();i++){
					ColumnDefine columnDef = new ColumnDefine();
					columnDef.setFieldName(entry.getValue().get(i));
					json.put(columnDef.getFieldName(), columnDef.getWarpName());
				}
				
				jsonArray.add(json);
			}
			
			sb.append(jsonArray.toString().replace("\"", "\\\""));
			sb.append("\")");
			return sb.toString();
		}else{
			return "";
		}
	}

}
